package com.have.blog.web.service.impl;


import com.github.pagehelper.PageHelper;
import com.have.blog.base.enums.BlogPublishStatus;
import com.have.blog.base.enums.BlogStatus;
import com.have.blog.base.wrapper.Wrapper;
import com.have.blog.config.hloder.RequestHolder;
import com.have.blog.model.mapper.BlogCategoryMapper;
import com.have.blog.model.mapper.BlogMapper;
import com.have.blog.model.mapper.BlogTagRelationMapper;
import com.have.blog.model.mapper.UserCommentMapper;
import com.have.blog.model.models.*;
import com.have.blog.picture.service.PictureFeignApi;
import com.have.blog.utils.MyBeanUtils;
import com.have.blog.web.constant.BlogConstant;
import com.have.blog.web.dto.BlogCategoryDto;
import com.have.blog.web.dto.BlogDto;
import com.have.blog.web.service.WebBlogService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.*;

@Service
@SuppressWarnings("all")
@Slf4j
public class WebBlogServiceImpl implements WebBlogService {
    @Autowired
    private BlogMapper blogMapper;
    @Autowired
    private PictureFeignApi pictureFeignApi;
    @Autowired
    private BlogCategoryMapper blogCategoryMapper;
    @Autowired
    private BlogTagRelationMapper blogTagRelationMapper;

    @Override
    public List<BlogDto> getBlogPageByLevel(Integer level, Integer pageNum, Integer useSort) {
        int pageSize = 0;
        switch (level) {
            case 0:
                pageSize = 15;
                break;
            case 1:
                pageSize = 5;
                break;
            case 2:
                pageSize = 2;
                break;
            case 3:
                pageSize = 3;
                break;
            case 4:
                pageSize = 5;

        }
        PageHelper.startPage(pageNum, pageSize);
        BlogExample example = new BlogExample();
        example.createCriteria()
                .andLevelEqualTo(level)
                .andStatusEqualTo(BlogStatus.ENABLE.getStatus())
                .andIsPublishEqualTo(BlogPublishStatus.PUBLISH.getStatus());
        List<Blog> blogList = blogMapper.selectByExample(example);

        // 当查询为一级推荐或者二级推荐时，填充top5到一级或者二级推荐中
        if ((level == BlogConstant.ONE || level == BlogConstant.TWO) && CollectionUtils.isEmpty(blogList)) {
            PageHelper.startPage(pageNum, 5);
            example.clear();
            example.createCriteria()
                    .andIsPublishEqualTo(BlogPublishStatus.PUBLISH.getStatus())
                    .andStatusEqualTo(BlogStatus.ENABLE.getStatus());
            example.setOrderByClause("click_count");
            blogList = blogMapper.selectByExample(example);
        }
        List<BlogDto> resultList = MyBeanUtils.copyListProperties(blogList, BlogDto::new);
        if (!CollectionUtils.isEmpty(resultList)) {
            addPicture(resultList);
            addCategory(resultList);
        }
        return resultList;
    }

    @Override
    public List<BlogDto> getHotBlog() {
        PageHelper.startPage(1, 15);
        BlogExample example = new BlogExample();
        example.createCriteria()
                .andStatusEqualTo(BlogStatus.ENABLE.getStatus())
                .andIsPublishEqualTo(BlogPublishStatus.PUBLISH.getStatus());
        example.setOrderByClause("click_count desc");
        List<Blog> blogList = blogMapper.selectByExample(example);
        List<BlogDto> resultList = MyBeanUtils.copyListProperties(blogList, BlogDto::new);
        if (!CollectionUtils.isEmpty(resultList)) {
            addPicture(resultList);
            addCategory(resultList);
        }
        return resultList;
    }


    @Override
    public List<BlogDto> getNewBlog(Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        BlogExample example = new BlogExample();
        example.createCriteria()
                .andStatusEqualTo(BlogStatus.ENABLE.getStatus())
                .andIsPublishEqualTo(BlogPublishStatus.PUBLISH.getStatus());
        example.setOrderByClause("create_time desc");
        List<Blog> blogList = blogMapper.selectByExample(example);
        List<BlogDto> resultList = MyBeanUtils.copyListProperties(blogList, BlogDto::new);
        if (!CollectionUtils.isEmpty(resultList)) {
            addPicture(resultList);
            addCategory(resultList);
        }
        return resultList;
    }

    @Override
    public List<BlogDto> getBlogBySearch(Integer currentPage, Integer pageSize) {
        return null;
    }


    @Override
    public BlogDto selectBlogByUid(Integer uid) {
        BlogExample example = new BlogExample();
        example.createCriteria().andUidEqualTo(uid);
        List<Blog> blogList = blogMapper.selectByExampleWithBLOBs(example);
        List<BlogDto> resultList = MyBeanUtils.copyListProperties(blogList, BlogDto::new);
        if (!CollectionUtils.isEmpty(resultList)) {
            addCategory(resultList);
            addPicture(resultList);
            return resultList.get(0);
        }
        return null;
    }

    @Override
    public Set<String> getBlogTimeSortList() {
        // TODO redis
        BlogExample example = new BlogExample();
        example.createCriteria()
                .andStatusEqualTo(BlogStatus.ENABLE.getStatus())
                .andIsPublishEqualTo(BlogPublishStatus.PUBLISH.getStatus());
        example.setOrderByClause("create_time desc");
        List<Blog> blogList = blogMapper.selectByExample(example);

        List<BlogDto> resultList = MyBeanUtils.copyListProperties(blogList, BlogDto::new);
        // todo 给博客设置标签、分类、图片
        setTagAndSortAndPicture(resultList);

        Map<String, List<BlogDto>> map = new HashMap<>();
        Set<String> monthSet = new TreeSet<>();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月");
        for (BlogDto blog : resultList) {
            Date createTime = blog.getCreateTime();
            String month = sdf.format(createTime).toString();
            monthSet.add(month);

            List<BlogDto> tempList = map.getOrDefault(month, new ArrayList<>());
            tempList.add(blog);
            map.put(month, tempList);
        }

        return monthSet;
    }

    @Override
    public List<BlogDto> getArticleByMonth(String monthDate) {

        BlogExample example = new BlogExample();
        example.createCriteria()
                .andStatusEqualTo(BlogStatus.ENABLE.getStatus())
                .andIsPublishEqualTo(BlogPublishStatus.PUBLISH.getStatus());
        example.setOrderByClause("create_time desc");
        List<Blog> blogList = blogMapper.selectByExample(example);
        List<BlogDto> resultList = MyBeanUtils.copyListProperties(blogList, BlogDto::new);
        if (!CollectionUtils.isEmpty(resultList)) {
            addPicture(resultList);
            addCategory(resultList);
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月");
        Map<String, List<BlogDto>> map = new HashMap<>();
        for (BlogDto item : resultList) {
            Date createTime = item.getCreateTime();
            String month = sdf.format(createTime).toString();
            List<BlogDto> tempList = map.getOrDefault(month, new ArrayList<>());
            tempList.add(item);
            map.put(month, tempList);
        }
        return map.get(monthDate);
    }

    @Override
    public List<BlogDto> getSameBlogByBlogUid(Integer uid) {
        Blog blog = blogMapper.selectByPrimaryKey(uid);
        if (blog == null) {
            return new ArrayList<>();
        }
        PageHelper.startPage(1, 10);
        Integer blogCategoryUid = blog.getBlogCategoryUid();
        BlogExample example = new BlogExample();
        example.createCriteria()
                .andBlogCategoryUidEqualTo(blogCategoryUid)
                .andStatusEqualTo(BlogStatus.ENABLE.getStatus())
                .andIsPublishEqualTo(BlogPublishStatus.PUBLISH.getStatus());
        example.setOrderByClause("create_time desc");
        List<Blog> blogList = blogMapper.selectByExample(example);
        List<BlogDto> resultList = MyBeanUtils.copyListProperties(blogList, BlogDto::new);
        if (!CollectionUtils.isEmpty(resultList)) {
            addPicture(resultList);
            addCategory(resultList);
        }
        return resultList;
    }

    @Override
    public List<BlogDto> getListByBlogSortUid(Integer blogSortUid, Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        BlogExample example = new BlogExample();
        example.createCriteria()
                .andStatusEqualTo(BlogStatus.ENABLE.getStatus())
                .andBlogCategoryUidEqualTo(blogSortUid);
        List<Blog> blogList = blogMapper.selectByExample(example);
        List<BlogDto> resultList = MyBeanUtils.copyListProperties(blogList, BlogDto::new);
        return resultList;
    }

    @Override
    public List<BlogDto> searchBlogByTag(Integer tagUid, Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        BlogTagRelationExample tagRelationExample = new BlogTagRelationExample();
        tagRelationExample.createCriteria()
                .andTagUidEqualTo(tagUid);
        List<BlogTagRelation> blogTagRelations = blogTagRelationMapper.selectByExample(tagRelationExample);
        List<Integer> uids = new ArrayList<>();
        for (BlogTagRelation blogTagRelation : blogTagRelations) {
            uids.add(blogTagRelation.getBlogUid());
        }
        if (CollectionUtils.isEmpty(uids)) {
            return new ArrayList<>();
        }
        BlogExample blogExample = new BlogExample();
        blogExample.createCriteria()
                .andUidIn(uids)
                .andStatusEqualTo(BlogStatus.ENABLE.getStatus())
                .andIsPublishEqualTo(BlogPublishStatus.PUBLISH.getStatus());
        List<Blog> blogList = blogMapper.selectByExample(blogExample);
        List<BlogDto> resultList = MyBeanUtils.copyListProperties(blogList, BlogDto::new);
        return resultList;
    }

    @Override
    public List<BlogDto> getBlogByUids(List<Integer> uids) {
        BlogExample example = new BlogExample();
        example.createCriteria()
                .andStatusEqualTo(BlogStatus.ENABLE.getStatus())
                .andIsPublishEqualTo(BlogPublishStatus.PUBLISH.getStatus())
                .andUidIn(uids);
        example.setOrderByClause("sort_count desc");
        List<Blog> blogList = blogMapper.selectByExample(example);
        List<BlogDto> resultList = MyBeanUtils.copyListProperties(blogList, BlogDto::new);
        if (!CollectionUtils.isEmpty(resultList)) {
            addPicture(resultList);
            addCategory(resultList);
        }
        return resultList;
    }

    private void addPicture(List<BlogDto> blogList) {
        List<Integer> pictureUids = new ArrayList<>();
        blogList.forEach(item -> {
            if (item.getCoverUid() != null){
                pictureUids.add(item.getCoverUid());
            }
        });
        System.out.println(pictureUids);
        if (!CollectionUtils.isEmpty(pictureUids)) {
            Wrapper<Map<Integer, String>> wrapper = pictureFeignApi.getPicturesUrl(pictureUids);
            System.out.println(wrapper);
            if (wrapper.isSuccess()) {
                Map<Integer, String> picMap = wrapper.getData();
                for (BlogDto blogDto : blogList) {
                    blogDto.setPhotoUrl(picMap.get(blogDto.getCoverUid()));
                }
            }
        }
    }

    private void addCategory(List<BlogDto> blogList) {
        List<Integer> sortUids = new ArrayList<>();
        blogList.forEach(item -> {
            sortUids.add(item.getBlogCategoryUid());
        });

        BlogCategoryExample sortExample = new BlogCategoryExample();
        sortExample.createCriteria()
                .andStatusEqualTo(BlogStatus.ENABLE.getStatus())
                .andUidIn(sortUids);
        List<BlogCategory> categoryList = blogCategoryMapper.selectByExample(sortExample);
        List<BlogCategoryDto> blogCategoryDtos = MyBeanUtils.copyListProperties(categoryList, BlogCategoryDto::new);
        Map<Integer, BlogCategoryDto> categoryDtoMap = new HashMap<>();
        blogCategoryDtos.forEach(item -> {
            categoryDtoMap.put(item.getUid(), item);
        });
        for (BlogDto blog : blogList) {
            blog.setBlogCategory(categoryDtoMap.get(blog.getBlogCategoryUid()));
        }
    }

    public void setTagAndSortAndPicture(List<BlogDto> blogList) {
        if (!CollectionUtils.isEmpty(blogList)) {
        }
    }

    @Override
    public List<BlogDto> getBlogByKeyword(Integer pageNum, Integer pageSize, String keywords) {
        PageHelper.startPage(pageNum, pageSize);
        BlogExample example = new BlogExample();
        BlogExample.Criteria criteria1 = example.createCriteria()
                .andStatusEqualTo(BlogStatus.ENABLE.getStatus())
                .andIsPublishEqualTo(BlogPublishStatus.PUBLISH.getStatus());

        if (!StringUtils.isEmpty(keywords) && !StringUtils.isEmpty(keywords.trim())){
            criteria1.andTitleLike("%" + keywords + "%");
            BlogExample.Criteria criteria2 = example.createCriteria();
            criteria2.andStatusEqualTo(BlogStatus.ENABLE.getStatus())
                    .andIsPublishEqualTo(BlogPublishStatus.PUBLISH.getStatus())
                    .andSummaryLike("%" + keywords + "%");
            example.or(criteria2);
        }

        example.setOrderByClause("click_count desc");
        List<Blog> blogList = blogMapper.selectByExample(example);
        List<BlogDto> resultList = MyBeanUtils.copyListProperties(blogList, BlogDto::new);

        addPicture(resultList);
        addCategory(resultList);
        return resultList;
    }

    @Override
    public List<BlogDto> searchBlogByAuthor(String author, Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        BlogExample example = new BlogExample();
        example.createCriteria()
                .andStatusEqualTo(BlogStatus.ENABLE.getStatus())
                .andIsPublishEqualTo(BlogPublishStatus.PUBLISH.getStatus())
                .andAuthorEqualTo(author);
        example.setOrderByClause("create_time desc");
        List<Blog> blogList = blogMapper.selectByExample(example);
        List<BlogDto> resultList = MyBeanUtils.copyListProperties(blogList, BlogDto::new);
        setTagAndSortAndPicture(resultList);
        return resultList;
    }

    /**
     * 添加高亮
     *
     * @param str
     * @param keyword
     * @return
     */
    private String getHitCode(String str, String keyword) {
        if (StringUtils.isEmpty(keyword) || StringUtils.isEmpty(str)) {
            return str;
        }
        String startStr = "<span style = 'color:red'>";
        String endStr = "</span>";
        // 判断关键字是否直接是搜索的内容，否者直接返回
        if (str.equals(keyword)) {
            return startStr + str + endStr;
        }
        String lowerCaseStr = str.toLowerCase();
        String lowerKeyword = keyword.toLowerCase();
        String[] lowerCaseArray = lowerCaseStr.split(lowerKeyword);
        Boolean isEndWith = lowerCaseStr.endsWith(lowerKeyword);

        // 计算分割后的字符串位置
        Integer count = 0;
        List<Map<String, Integer>> list = new ArrayList<>();
        List<Map<String, Integer>> keyList = new ArrayList<>();
        for (int a = 0; a < lowerCaseArray.length; a++) {
            // 将切割出来的存储map
            Map<String, Integer> map = new HashMap<>();
            Map<String, Integer> keyMap = new HashMap<>();
            map.put("startIndex", count);
            Integer len = lowerCaseArray[a].length();
            count += len;
            map.put("endIndex", count);
            list.add(map);
            if (a < lowerCaseArray.length - 1 || isEndWith) {
                // 将keyword存储map
                keyMap.put("startIndex", count);
                count += keyword.length();
                keyMap.put("endIndex", count);
                keyList.add(keyMap);
            }
        }
        // 截取切割对象
        List<String> arrayList = new ArrayList<>();
        for (Map<String, Integer> item : list) {
            Integer start = item.get("startIndex");
            Integer end = item.get("endIndex");
            String itemStr = str.substring(start, end);
            arrayList.add(itemStr);
        }
        // 截取关键字
        List<String> keyArrayList = new ArrayList<>();
        for (Map<String, Integer> item : keyList) {
            Integer start = item.get("startIndex");
            Integer end = item.get("endIndex");
            String itemStr = str.substring(start, end);
            keyArrayList.add(itemStr);
        }

        StringBuffer sb = new StringBuffer();
        for (int a = 0; a < arrayList.size(); a++) {
            sb.append(arrayList.get(a));
            if (a < arrayList.size() - 1 || isEndWith) {
                sb.append(startStr);
                sb.append(keyArrayList.get(a));
                sb.append(endStr);
            }
        }
        return sb.toString();
    }


    @Autowired
    private UserCommentMapper commentMapper;
    /**
     * 点赞字段要改，每次都去查点赞表效率低下，用户明显不会常去查看点赞详情，更多注意点赞数量
     * @param uid
     * @return
     */
    @Override
    public Wrapper praiseBlogByUid(Integer uid) {
        BlogExample example = new BlogExample();
        example.createCriteria()
                .andStatusEqualTo(BlogStatus.ENABLE.getStatus())
                .andUidEqualTo(uid);
        List<Blog> blogs = blogMapper.selectByExample(example);
        if (CollectionUtils.isEmpty(blogs)) {
            return Wrapper.illegal();
        }
        HttpServletRequest request = RequestHolder.getRequest();
        Integer userId = Integer.valueOf(request.getAttribute(BlogConstant.USER_UID).toString());
        UserCommentExample commentExample = new UserCommentExample();
        commentExample.createCriteria()
                .andStatusEqualTo(BlogStatus.ENABLE.getStatus())
                .andBlogUidEqualTo(uid)
                .andUserUidEqualTo(userId)
                .andTypeEqualTo(1);
        List<UserComment> praiseList = commentMapper.selectByExample(commentExample);
        if (!CollectionUtils.isEmpty(praiseList)) {
            return Wrapper.success();
        }

        UserComment comment = new UserComment();
        comment.setStatus(BlogStatus.ENABLE.getStatus());
        comment.setBlogUid(uid);
        comment.setUserUid(userId);
        comment.setType(1);
        comment.setSource("BLOG_INFO");
        int result = commentMapper.insert(comment);
        if (result > 0){
            return getBlogPraiseCountByUid(uid);
        }
        return Wrapper.failed();
    }

    @Override
    public Wrapper getBlogPraiseCountByUid(Integer uid) {
        UserCommentExample example = new UserCommentExample();
        example.createCriteria()
                .andStatusEqualTo(BlogStatus.ENABLE.getStatus())
                .andBlogUidEqualTo(uid)
                .andTypeEqualTo(1);
        long count = commentMapper.countByExample(example);
        return Wrapper.success(count);
    }
}
